package com.wsoft.cms.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.github.pagehelper.PageInfo;
import com.wsoft.cms.entity.CmsAnnouncementEntity;
import com.wsoft.cms.entity.CmsAnnouncementReadEntity;
import com.wsoft.cms.entity.CmsAnnouncementSignEntity;
import com.wsoft.cms.entity.CmsAnnouncementSummaryEntity;
import com.wsoft.cms.enums.CategoryLevelEnum;
import com.wsoft.cms.enums.SummaryTypeEnum;
import com.wsoft.cms.manager.*;
import com.wsoft.cms.mapper.CmsAnnouncementMapper;
import com.wsoft.cms.query.announcement.*;
import com.wsoft.cms.service.ICmsAnnouncementService;
import com.wsoft.cms.vo.anno.AnnouncementListVO;
import com.wsoft.cms.vo.anno.AnnouncementVO;
import com.wsoft.cms.vo.category.CmsCategoryInfoVO;
import com.wsoft.core.exception.Asserts;
import com.wsoft.core.utils.LoginUserUtil;
import com.wsoft.enums.PublishStatusEnum;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * <p>
 * 新闻公告表 服务实现类
 * </p>
 *
 * @author juiet
 * @since 2024年11月27日 10:32:23
 */
@Service
public class CmsAnnouncementServiceImpl extends ServiceImpl<CmsAnnouncementMapper, CmsAnnouncementEntity> implements ICmsAnnouncementService {

    @Resource
    private CmsAnnouncementManager announcementManager;
    @Resource
    private CmsCategoryManager categoryManager;
    @Resource
    private CmsAnnouncementSummaryManager summaryManager;
    @Resource
    private CmsAnnouncementFileManager fileManager;
    @Resource
    private CmsAnnouncementReadManager readManager;
    @Resource
    private CmsAnnouncementSignManager signManager;

    /**
     * 新增新闻公告
     *
     * @param query
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean insertAnno(AnnouncementInsertQuery query) {
        CmsAnnouncementEntity entity = Convert.convert(CmsAnnouncementEntity.class, query);
        //新增默认未发布状态
        entity.setSendStatus(PublishStatusEnum.NOT_PUBLISH.getType());
        //处理工作流
        handlerBmp(entity);

        //保存公告
        announcementManager.save(entity);
        //保存附件
        fileManager.saveBatch(entity.getId(),query.getFileList());
        return true;
    }

    /**
     * 修改新闻公告
     *
     * @param query
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean updateAnno(AnnouncementUpdateQuery query) {
        CmsAnnouncementEntity announcement = announcementManager.getById(query.getId());
        if (PublishStatusEnum.PUBLISH.getType().equals(announcement.getSendStatus())) {
            //发布状态不允许修改
            Asserts.fail("[cms.publishStatus.error]");
        }
        //判断 当前状态,是否可以修改
        CmsAnnouncementEntity entity = Convert.convert(CmsAnnouncementEntity.class, query);
        //处理工作流
        handlerBmp(entity);
        //更新公告
        announcementManager.updateById(entity);
        //更新附件
        fileManager.updateBatch(query.getId(),query.getFileList());

        return true;
    }

     /**
     * 获取公告详情 -- 计算浏览量
     *
     * @param id
     * @return
     */
    @Override
    public AnnouncementVO getInfoByUser(Long id) {
        AnnouncementListQuery listQuery = new AnnouncementListQuery();
        List<CmsAnnouncementEntity> list = announcementManager.listAnnoQuery(listQuery, true, id);
        if(CollUtil.isEmpty(list)){
            //无权限查看
            Asserts.fail("[cms.view.error]");
        }
        CmsAnnouncementEntity entity = announcementManager.getById(id);
        if (!entity.getSendStatus().equals(PublishStatusEnum.PUBLISH.getType())) {
            Asserts.fail("[cms.view.error]");
        }
        AnnouncementVO vo = announcementManager.getAnnoInfoById(entity);

        //浏览数 + 1
        summaryManager.addCount(id, SummaryTypeEnum.VIEW.getType(), 1);

        //记录 已读用户
        readManager.read(id, LoginUserUtil.getUserInfo().getLoginUserVO().getId());

        if( 1 == vo.getAnnoInfo().getIsSign()){
            //允许报名
            CmsAnnouncementSignEntity sign = signManager.getByAnnoIdAndMemberId(id, LoginUserUtil.getUserInfo().getLoginUserVO().getId());
            if(sign != null){
                vo.setUserSign(true);
            }else{
                vo.setUserSign(false);
            }
        }
        return vo;
    }

    /**
     * 获取公告详情 -- 不计算浏览量
     *
     * @param id
     * @return
     */
    @Override
    public AnnouncementVO getInfoByAdmin(Long id) {
        CmsAnnouncementEntity entity = announcementManager.getById(id);
        return announcementManager.getAnnoInfoById(entity);
    }

    /**
     * 发布公告
     *
     * @param id
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean publish(AnnouncementPublishQuery query) {
        CmsAnnouncementEntity entity = announcementManager.getById(query.getId());
        if (PublishStatusEnum.PUBLISH.getType().equals(entity.getSendStatus()) ||
                entity.getStatus() != 2) {
            //状态不正确
            Asserts.fail("[cms.publishStatus.error]");
        }

        if(null == entity.getSendMemberId() || null == entity.getSendOrgId()){
            //发布参数错误
            Asserts.fail("[cms.publish.param.error]");
        }

        // 比较时间
        if (query.getSendTime().isAfter(LocalDateTime.now())) {
            //走定时
            entity.setSendStatus(PublishStatusEnum.WAIT_PUBLISH.getType());
        } else{
            //立即发布
            entity.setSendStatus(PublishStatusEnum.PUBLISH.getType());
        }
        entity.setSendTime(query.getSendTime());
        announcementManager.updateById(entity);

        CmsAnnouncementSummaryEntity summary = summaryManager.getById(query.getId());
        if(null == summary){
            //新增统计数,默认都是0
            summary = new CmsAnnouncementSummaryEntity();
            summary.setAnnoId(query.getId());
            summary.setCommentNum(0L);
            summary.setViewNum(0L);
            summary.setSignNum(0L);
            summaryManager.save(summary);
        }
        return true;
    }

    /**
     * 撤销公告
     *
     * @param id
     * @return
     */
    @Override
    public boolean cancel(Long id) {
        CmsAnnouncementEntity entity = announcementManager.getById(id);
        if(null == entity){
            return false;
        }
        if(!PublishStatusEnum.PUBLISH.getType().equals(entity.getSendStatus())
                && !PublishStatusEnum.WAIT_PUBLISH.getType().equals(entity.getSendStatus())){
            //状态不正确
            Asserts.fail("[cms.publishStatus.error]");
        }
        entity.setSendStatus(PublishStatusEnum.CANCEL.getType());
        entity.setCancelTime(LocalDateTime.now());
        return announcementManager.updateById(entity);
    }

    @Override
    public PageInfo listAnno(AnnouncementListQuery query, boolean isUser) {
        return announcementManager.listAnno(query,isUser);
    }

    @Override
    public boolean allRead() {
        AnnouncementListQuery query = new AnnouncementListQuery();
        PageInfo pageInfo = announcementManager.listAnno(query,true);
        List<AnnouncementListVO> list = pageInfo.getList();
        if(CollUtil.isNotEmpty(list)){
            LocalDateTime now = LocalDateTime.now();
            Long memberId = LoginUserUtil.getUserInfo().getLoginUserVO().getId();
            //已读用户列表
            Set<Long> readMemberSet = readManager.getByMemberId(memberId);
            List<CmsAnnouncementReadEntity> readList = new ArrayList<>();
            list = list.stream().filter(item-> !readMemberSet.contains(item.getId())).collect(Collectors.toList());
            for (AnnouncementListVO entity : list) {
                CmsAnnouncementReadEntity read = new CmsAnnouncementReadEntity();
                read.setAnnoId(entity.getId());
                read.setReadTime(now);
                read.setMemberId(memberId);
                read.setReadFlag(1);
                readList.add(read);
            }
            readManager.saveBatch(memberId,readList);
        }
        return true;
    }

    @Override
    public boolean delete(Long id) {
        return announcementManager.removeById(id);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean updateFile(AnnouncementFileUpdateQuery query) {
        //更新附件
        fileManager.updateBatch(query.getId(),query.getFileList());
        return true;
    }

    // ################################## 私有方法  ##################################

    /**
     * 处理公告工作流,是否继承上级
     *
     * @param entity
     */
    public void handlerBmp(CmsAnnouncementEntity entity) {
        if (StrUtil.isNotBlank(entity.getBusinessCode())) {
            //如果有值,则进工作流
            entity.setStatus(0);
            return;
        }
        Long categoryId = entity.getCategoryId();
        CmsCategoryInfoVO categoryEntity = categoryManager.getById(categoryId);
        if (categoryEntity.getBpmFlag().equals(0)) {
            //上级不启用工作流,则工作流状态直接置为2
            entity.setStatus(2);
        } else {
            //上级启用工作流,获取上级工作流 businessCode
            String businessCode = categoryEntity.getBusinessCode();
            if (StrUtil.isBlank(businessCode) &&
                    Objects.equals(categoryEntity.getLevel(), CategoryLevelEnum.TWO.getType())) {
                CmsCategoryInfoVO byId = categoryManager.getById(categoryEntity.getPaId());
                businessCode = byId.getBusinessCode();
            }
            if (StrUtil.isNotBlank(businessCode)) {
                //上级不为空,则默认继承上级工作流key
                entity.setBusinessCode(businessCode);
                entity.setStatus(0);
            } else {
                //上级为空,则状态直接置为2
                entity.setStatus(2);
            }
        }

    }
}
